package com.qf.game.service;

import com.alibaba.fastjson.JSONObject;
import com.qf.game.entity.Player;
import com.qf.game.utils.IdGeneratorUtils;
import com.qf.game.utils.RoomManagerUtils;
import com.qf.game.utils.SessionUtils;
import com.qf.game.websocket.entity.ChessBoard;
import com.qf.game.websocket.entity.PlayerInfo;
import com.qf.game.websocket.entity.Room;

import javax.websocket.Session;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 游戏的业务层
 *
 * description:
 * author: Ken
 * 公众号：Java架构栈
 */
public class GameService {


    private PlayerService playerService = new PlayerService();

    /**
     * 创建游戏房间
     * @param room
     * @return
     */
    public Integer createRoom(Room room){
        //通过id生成器生成房间id
        room.setRid(IdGeneratorUtils.generatorId());
        //初始化房间棋盘
        room.setChessBoard(new ChessBoard(17));
        //设置房间的状态
        room.setStatus(0);//等待玩家的加入
        //将房间放入房间管理器
        RoomManagerUtils.addRoom(room);
        return room.getRid();
    }

    /**
     * 加入房间
     * {"type":100,"rid":3,
     * "pid":12,
     * "header":"fa550497-0180-4d97-8686-fa7f9b7b9db6",
     * "nickname":"小明",
     * "level":0}
     *
     * 返回
     * {"type":200} - 当前房间未找到
     *
     * {"type":201, "rid":rid, "title":"标题", "looks":"观战人数"} - 正常加入房间
     */
    public void addRoom(JSONObject jsonObject, Session session){

        //1、获取加入的房间号
        int rid = jsonObject.getIntValue("rid");
        //2、通过房间号获取房间对象
        Room room = RoomManagerUtils.getRoomById(rid);

        //判断房间是否为null
        if (room == null) {
            //房间号对应的房间不存在
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("type", 200);//房间不存在

            //发送给客户端
            SessionUtils.sendMsg(session, resultMap);
            return;
        }

        //找到房间，给当前房间设置玩家对象
        int pid = jsonObject.getIntValue("pid");
        String header = jsonObject.getString("header");
        String nick = jsonObject.getString("nickname");
        int level = jsonObject.getIntValue("level");
        int looks = jsonObject.getIntValue("looks");//0-加入对局 1-观看对局

        //玩家基本信息对象
        Player player = new Player()
                .setId(pid)
                .setNickname(nick)
                .setHeader(header)
                .setLevel(level);

        //玩家对象
        PlayerInfo playerInfo = new PlayerInfo()
                .setPlayer(player)
                .setSession(session);

        synchronized ((rid + "").intern()) {

            //当前玩家需要加入对局
            if (looks == 0) {

                //判断房间状态
                if (room.getStatus() == 1) {
                    //房间号对应的房间不存在
                    Map<String, Object> resultMap = new HashMap<>();
                    resultMap.put("type", 203);//房间人数已满

                    //发送给客户端
                    SessionUtils.sendMsg(session, resultMap);
                    return;
                }

                //将玩家信息 放入房间
                int result = room.addPlayerInfo(playerInfo);
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("type", 201);//房间加入成功
                resultMap.put("rid", rid);//房间号
                resultMap.put("title", room.getTitle());//房间标题
                resultMap.put("looks", room.getLooks() == null ? 0 : room.getLooks().size());//观战人数
                //返回给当前的玩家
                SessionUtils.sendMsg(session, resultMap);

                if (result == 1) {
                    //有两个玩家，游戏开启
                    //修改房间状态
                    room.setStatus(1);

                    //互相交换信息
                    //将2号玩家的信息 告诉 1号玩家
                    Map<String, Object> resultMap1 = new HashMap<>();
                    resultMap1.put("type", 202);//房间加入成功，并且开始游戏
                    resultMap1.put("pid", room.getPlayerInfo2().getPlayer().getId());
                    resultMap1.put("header", room.getPlayerInfo2().getPlayer().getHeader());
                    resultMap1.put("nickname", room.getPlayerInfo2().getPlayer().getNickname());
                    resultMap1.put("level", room.getPlayerInfo2().getPlayer().getLevel());
                    resultMap1.put("firststep", true);
                    SessionUtils.sendMsg(room.getPlayerInfo1().getSession(), resultMap1);

                    //将1号玩家的信息 告诉 2号玩家
                    Map<String, Object> resultMap2 = new HashMap<>();
                    resultMap2.put("type", 202);//房间加入成功，并且开始游戏
                    resultMap2.put("pid", room.getPlayerInfo1().getPlayer().getId());
                    resultMap2.put("header", room.getPlayerInfo1().getPlayer().getHeader());
                    resultMap2.put("nickname", room.getPlayerInfo1().getPlayer().getNickname());
                    resultMap2.put("level", room.getPlayerInfo1().getPlayer().getLevel());
                    resultMap2.put("firststep", false);
                    SessionUtils.sendMsg(room.getPlayerInfo2().getSession(), resultMap2);
                }
            }
            else {
                //当前玩家需要观看对局
                room.addLookPlayerInfo(playerInfo);

                //更新双方玩家的所有观战人数
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("type", 206);
                resultMap.put("looksNum", room.getLooks().size());

                //发送给第一个玩家
                SessionUtils.sendMsg(room.getPlayerInfo1().getSession(), resultMap);
                //发送给第二个玩家
                if (room.getPlayerInfo2() != null) {
                    SessionUtils.sendMsg(room.getPlayerInfo2().getSession(), resultMap);
                }
                //发送给所有其他的观战者
                for (PlayerInfo lookPlayerInfo : room.getLooks()) {
                    SessionUtils.sendMsg(lookPlayerInfo.getSession(), resultMap);
                }

                //房间信息 -> 当前的观战者
                Map<String, Object> resultMap2 = new HashMap<>();
                resultMap2.put("type", 201);//房间加入成功
                resultMap2.put("rid", rid);//房间号
                resultMap2.put("title", room.getTitle());//房间标题
                resultMap2.put("looks", room.getLooks() == null ? 0 : room.getLooks().size());//观战人数
                //返回给当前的玩家
                SessionUtils.sendMsg(session, resultMap2);

                //双方的玩家信息 -> 当前的观战者
                Map<String, Object> resultMap3 = new HashMap<>();
                resultMap3.put("type", 207);
                resultMap3.put("pid", room.getPlayerInfo1().getPlayer().getId());
                resultMap3.put("header", room.getPlayerInfo1().getPlayer().getHeader());
                resultMap3.put("nickname", room.getPlayerInfo1().getPlayer().getNickname());
                resultMap3.put("level", room.getPlayerInfo1().getPlayer().getLevel());
                //返回给当前的玩家
                SessionUtils.sendMsg(session, resultMap3);

                //判断玩家2是否存在
                if (room.getPlayerInfo2() != null) {
                    Map<String, Object> resultMap4 = new HashMap<>();
                    resultMap4.put("type", 208);
                    resultMap4.put("pid", room.getPlayerInfo2().getPlayer().getId());
                    resultMap4.put("header", room.getPlayerInfo2().getPlayer().getHeader());
                    resultMap4.put("nickname", room.getPlayerInfo2().getPlayer().getNickname());
                    resultMap4.put("level", room.getPlayerInfo2().getPlayer().getLevel());
                    //返回给当前的玩家
                    SessionUtils.sendMsg(session, resultMap4);
                }

                //如果有棋局信息，棋局信息需要全部发送给当前的观察者
                List<ChessBoard.Point> allPoint = room.getChessBoard().getAllPoint();
                Map<String, Object> resultMap5 = new HashMap<>();
                resultMap5.put("type", 209);
                resultMap5.put("points", allPoint);
                //返回给当前的玩家
                SessionUtils.sendMsg(session, resultMap5);
            }
        }
    }

    /**
     * 游戏落子的方法
     * @param jsonObject
     * @param session
     */
    public void go(JSONObject jsonObject, Session session) {
        //获取落子方的参数
        int rid = jsonObject.getIntValue("rid");
        int x = jsonObject.getIntValue("x");
        int y = jsonObject.getIntValue("y");
        int color = jsonObject.getIntValue("color");

        //获得对手的session
        Room room = RoomManagerUtils.getRoomById(rid);
        //判断当前位置是否可以落子
        boolean flag = room.getChessBoard().go(x,y,color);
        if (!flag) {
            return;
        }

        //判断输赢
        boolean isWin = room.getChessBoard().isWin(x, y, color);

        if (isWin) {
            //游戏胜利，进行相关的业务处理
            //胜利的一方 添加欢乐豆
            PlayerInfo player = room.getPlayer(session);
            playerService.updatePlayerHappyBean(1000, 0, player.getPlayer().getId());

            //失败的一方 扣减欢乐豆
            PlayerInfo player2 = room.getOtherPlayer(session);
            playerService.updatePlayerHappyBean(1000, 1, player2.getPlayer().getId());

            //生成两条流水记录
        }

        //落子成功
        Map<String, Object> resultMap1 = new HashMap<>();
        resultMap1.put("type", 205);//落子成功
        resultMap1.put("x", x);
        resultMap1.put("y", y);
        resultMap1.put("color", color);
        resultMap1.put("isWin", isWin ? 1 : 0);
        SessionUtils.sendMsg(session, resultMap1);

        //获得对手信息
        PlayerInfo otherPlayer = room.getOtherPlayer(session);
        //组装需要发送的Map
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("type", 204);//对方的落子信息
        resultMap.put("x", x);
        resultMap.put("y", y);
        resultMap.put("color", color);
        resultMap.put("isWin", isWin ? 2 : 0);
        SessionUtils.sendMsg(otherPlayer.getSession(), resultMap);

        //发给所有的观察者
        List<PlayerInfo> looks = room.getLooks();
        if (looks != null && looks.size() > 0) {
            for (PlayerInfo look : looks) {
                Map<String, Object> resultMap2 = new HashMap<>();
                resultMap2.put("type", 210);//对方的落子信息
                resultMap2.put("x", x);
                resultMap2.put("y", y);
                resultMap2.put("color", color);
                PlayerInfo player = room.getPlayer(session);
                resultMap2.put("isWin", isWin ? player.getPlayer().getNickname() : null);

                SessionUtils.sendMsg(look.getSession(), resultMap2);
            }
        }
    }

    /**
     * 断开连接的处理方法
     */
    public void closeSession(Session session){
        //获得当前session对应的房间
        Room room = RoomManagerUtils.getRoomBySession(session);
        if (room == null) return;

        synchronized ((room.getRid() + "").intern()) {

            //判断当前session是否为观察者
            List<PlayerInfo> looks = room.getLooks();
            if (looks != null && looks.size() > 0) {
                for (PlayerInfo look : new ArrayList<>(looks)) {
                    if (look.getSession() == session) {
                        //当前断开连接的是一个观察者
                        looks.remove(look);

                        //更新所有其他人的观察者数量
                        Map<String, Object> resultMap = new HashMap<>();
                        resultMap.put("type", 206);
                        resultMap.put("looksNum", room.getLooks().size());
                        //发送给第一个玩家
                        if (room.getPlayerInfo1() != null) {
                            SessionUtils.sendMsg(room.getPlayerInfo1().getSession(), resultMap);
                        }
                        //发送给第二个玩家
                        if (room.getPlayerInfo2() != null) {
                            SessionUtils.sendMsg(room.getPlayerInfo2().getSession(), resultMap);
                        }
                        //发送给所有其他的观战者
                        for (PlayerInfo lookPlayerInfo : looks) {
                            SessionUtils.sendMsg(lookPlayerInfo.getSession(), resultMap);
                        }
                        return;
                    }
                }
            }

            //判断当前的房间状态
            if (room.getPlayerNum() == 1) {
                //删除当前房间
                RoomManagerUtils.removeRoom(room.getRid());
            } else if (room.getPlayerNum() == 2) {
                //发送消息给对手
                PlayerInfo otherPlayer = room.getOtherPlayer(session);

                //移除当前房间的玩家信息
                room.removePlayer(session);

                //胜利的信息给对方
                Map<String, Object> msg = new HashMap<>();
                msg.put("type", 211);
                //
                SessionUtils.sendMsg(otherPlayer.getSession(), msg);
            }
        }
    }
}
